package com.zeyu.soc.log.profiler;

import java.io.PrintStream;

import com.zeyu.soc.log.profiler.core.ContextData;
import com.zeyu.soc.log.profiler.core.ContextNode;
import com.zeyu.soc.log.profiler.core.TraceManager;
import com.zeyu.soc.log.profiler.core.TraceManagerImpl;

/**
 * 分析器
 */
public class Profiler {

	// ================================================================
	// Constants
	// ================================================================

	// time
	private static int ELAPSE_TIME_MS_TO_LOG = 500;

	// 保存线程安全context data
	private final static ThreadLocal<ContextData> dataHolder = new ThreadLocal<ContextData>();

	// ================================================================
	// Fields
	// ================================================================

	// 处理器
	private static TraceManager traceManager = new TraceManagerImpl(System.out);

	// ================================================================
	// Constructors
	// ================================================================

	// ================================================================
	// Methods from/for super Interfaces or SuperClass
	// ================================================================

	// ================================================================
	// Public or Protected Methods
	// ================================================================

	/**
	 * 启动记录器
	 */
	public static void start(String logName) {
		start(logName, ELAPSE_TIME_MS_TO_LOG);
	}

	/**
	 * 初始化一个新的处理器
	 */
	public static void init(PrintStream out) {
		traceManager = new TraceManagerImpl(out);
	}

	/**
	 * 启动记录器
	 */
	public static void start(String logName, int elapseTimeMsToLog) {
		ContextData execData = dataHolder.get();
		ContextNode currentNode = new ContextNode(logName, System.currentTimeMillis(), elapseTimeMsToLog);
		if (execData == null) {
			execData = new ContextData();
			execData.root = currentNode;
			dataHolder.set(execData);
		} else {
			ContextNode parent = execData.currentNode;
			currentNode.setParent(parent);
			parent.getChildList().add(currentNode);
		}
		execData.currentNode = currentNode;
		execData.level++;
	}

	/**
	 * 停止记录器
	 */
	public static void stop(String matchLogNameWithStart) {
		ContextData execData = dataHolder.get();
		long nowTime = System.currentTimeMillis();
		execData.currentNode.setEndTime(nowTime);
		ContextNode child = execData.currentNode;
		execData.currentNode = child.getParent();
		execData.level--;
		if (execData.level == 0) {
			if ((nowTime - execData.root.getStartTime()) >= execData.root.getElapseTimeMsToLog() || execData.showflag) {
				traceManager.showTree(execData.root);
			}
			dataHolder.remove();
		} else {
			if (child.getExecTime() >= child.getElapseTimeMsToLog()) {
				execData.showflag = true;
			}
		}
	}

	// ================================================================
	// Getter & Setter
	// ================================================================

	// ================================================================
	// Private Methods
	// ================================================================

	// ================================================================
	// Inner or Anonymous Class
	// ================================================================

	// ================================================================
	// Test Methods
	// ================================================================
}
